
`include "common_header.verilog"

//  *************************************************************************
//  File : check_pat824964.v
//  *************************************************************************
//  This program is controlled by a written license agreement.
//  Unauthorized reproduction or use is expressly prohibited.
//  Copyright (c) 2008 MorethanIP
//  Muenchner Strasse 199, 85757 Karlsfeld, Germany
//  info@morethanip.com
//  http://www.morethanip.com
//  *************************************************************************
//  Designed by : Daniel Koehler
//  info@morethanip.com
//  *************************************************************************
//  Description : Configurable Clause 49/82 Test Pattern Checker
//  Version     : $Id: check_pat824964.v,v 1.1 2014/10/20 08:17:55 dk Exp $
//  *************************************************************************
module check_pat824964 (

        reset,
        clk,
        clk_ena,
        r_test_mode,
        en_chk_pat49,
        sel_pat,
        block_lock,
        data_in,
        sh_in,
        pat_err_cnt_rd,
        pat_err_cnt);

input           reset;                  //  asynch reset
input           clk;                    //  system clock
input           clk_ena;                //  clock enable, input valid.
input           r_test_mode;            //  Receive test pattern mode
input           en_chk_pat49;           //  Enable 10G Test pattern checker (49.2.12) 
input           sel_pat;                //  Select pattern : 1 => 00 / 0 => Local Fault 
input           block_lock;             //  Lock state reached
input   [63:0]  data_in;                //  Data from descrambler
input   [1:0]   sh_in;                  //  sync header of block
input           pat_err_cnt_rd;         //  Test pattern error counter read (clock cycle pulse)
output  [15:0]  pat_err_cnt;            //  Test pattern error counter

wire    [15:0]  pat_err_cnt; 

reg             check_en;               //  Enable check pattern
wire            error_inc;              //  increment error counter
reg     [6:0]   cnt128;                 //  Clause 49 allow one error every 128 blocks.
reg             inc_ok;                 //  allow error counter increment
reg     [1:0]   match49;                //  Clause 49 matches
reg             match82;                //  Clause 82 matches
reg             sh_good;                //  sync header is good (aligned with matches)
wire            pattern_good;           //  data matches expected pattern

//  Compare patterns
//  -------------------------
always @(posedge clk or posedge reset)
begin : pmatch
        if (reset == 1'b 1)
        begin
                match49 <= 2'b 00;
                match82 <= 1'b 0;
                sh_good <= 1'b 0;
        end
        else
        begin
                // compare all possible patterns, for timing all individually
                
                if( clk_ena == 1'b 1 )
                begin
                        if(data_in == 64'h 0100000001000055 ||  // 2x LF
                           data_in == 64'h fefffffffeffffaa)    // 2x LF, inverted
                        begin
                                match49[0] <= 1'b 1;
                        end
                        else
                        begin
                                match49[0] <= 1'b 0;
                        end

                        if(data_in == 64'h 0000000000000000 ||  // Zero
                           data_in == 64'h ffffffffffffffff)    // Zero, inverted
                        begin
                                match49[1] <= 1'b 1;
                        end
                        else
                        begin
                                match49[1] <= 1'b 0;
                        end

                        if(data_in == 64'h 000000000000001E)    // IDLE
                        begin
                                match82 <= 1'b 1;
                        end
                        else
                        begin
                                match82 <= 1'b 0;
                        end

                        // align sync header with match results.
                        
                        if( sh_in == 2'b 01 )
                        begin
                                sh_good <= 1'b 1;
                        end
                        else                
                        begin
                                sh_good <= 1'b 0;
                        end

                end
                
        end
end


//  determine check allowance
//  -------------------------

always @(posedge clk or posedge reset)
   begin : process_1
   if (reset == 1'b 1)
      begin
      check_en <= 1'b 0;	//  Enable check pattern
      cnt128   <= 7'd 0;
      inc_ok   <= 1'b 0;
      end
   else
      begin
        
        if (r_test_mode == 1'b 1 & block_lock == 1'b 1)
        begin
                check_en <= 1'b 1;	
        end
        else
        begin
                check_en <= 1'b 0;	
        end
        
        // Clause 49, 128 blocks count to mask 1 in 128.
        
        if( clk_ena == 1'b 1 )
        begin
        
                if( check_en == 1'b 1 && en_chk_pat49 == 1'b 1 )
                begin
                        cnt128 <= cnt128 + 7'd 1;
                end
        
                if( en_chk_pat49 == 1'b 1 && cnt128 == 7'b 1111111 )
                begin
                        inc_ok <= 1'b 0;     // ignore first error within 128
                end
                else if( en_chk_pat49 == 1'b 0 || pattern_good == 1'b 0 )
                begin
                        inc_ok <= 1'b 1;
                end
                
        end
         
      end
   end

assign pattern_good = sh_good == 1'b 1 && (
                        (en_chk_pat49 == 1'b 0 && match82 == 1'b 1) ||                          // IDLE
                        (en_chk_pat49 == 1'b 1 && sel_pat == 1'b 0 && match49[0] == 1'b 1) ||   // 2x LF
                        (en_chk_pat49 == 1'b 1 && sel_pat == 1'b 1 && match49[1] == 1'b 1)      // Zero
                        ) ? 1'b 1 : 1'b 0;
                      

assign error_inc = r_test_mode & inc_ok & ~pattern_good; 
 

//  the error counter taking up to 3 events per cycle
//  -------------------------------------------------
sat_counter_evt3 #(16) U_ERRCNT (
          .reset(reset),
          .clk(clk),
          .clk_ena(clk_ena),
          .inc_event({2'b 00,error_inc}),        //  per lane event
          .count_ena(check_en),         //  allow counting
          .count_rd(pat_err_cnt_rd),
          .count_value(pat_err_cnt));

endmodule // module check_pat824964

